using DA.AnimGraph;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;

namespace DA.AnimGraph.Editor {
    internal class AGAFieldModel_FloatLink : AGAFieldModelBase {
        public LinkSourceType sourceType;
        public AUID blackboardKey;
        public float defaultValue;
        public bool useClamp;
        public float2 clampRange;
        public float easeTime;
        public EaseType easeType;
        public EaseFunctionType easeFunctionType;

        public AGAFieldModel_FloatLink() {
            clampRange = new float2(0f, 1f);
        }

        public FloatLinkDesc Publish(AGAPublisher.PublishContext context) {
            AUID name = default;
            if (context.blackboard.GetEntry(blackboardKey, out var entry)) {
                name = entry.name;
            }

            return new FloatLinkDesc() {
                name = name,
                sourceType = sourceType,
                defaultValue = defaultValue,
                useClamp = useClamp,
                clampRange = clampRange,
                easeTime = easeTime,
                easeType = easeType,
                easeFunctionType = easeFunctionType,
            };
        }
    }

    internal class AGAFieldModel_IntLink : AGAFieldModelBase {
        public LinkSourceType sourceType;
        public AUID blackboardKey;
        public int defaultValue;

        public IntLinkDesc Publish(AGAPublisher.PublishContext context) {
            AUID name = default;
            if (context.blackboard.GetEntry(blackboardKey, out var entry)) {
                name = entry.name;
            }

            return new IntLinkDesc() {
                name = name,
                sourceType = sourceType,
                defaultValue = defaultValue,
            };
        }
    }

    internal class AGAFieldModel_Vector2Link {
        public LinkSourceType sourceType;
        public AUID blackboardKey;
        public float2 defaultValue;
        public bool useClamp;
        public float2 clampRangeX;
        public float2 clampRangeY;

        public Vector2LinkDesc Publish(AGAPublisher.PublishContext context) {
            AUID name = default;
            if (context.blackboard.GetEntry(blackboardKey, out var entry)) {
                name = entry.name;
            }

            return new Vector2LinkDesc() {
                name = name,
                sourceType = sourceType,
                defaultValue = defaultValue,
                useClamp = useClamp,
                clampRangeX = clampRangeX,
                clampRangeY = clampRangeY,
            };
        }
    }

    internal class AGAFieldModel_Transition : AGAFieldModelBase {
        public int sourceState; // -1代表任意状态
        public int targetState;
        public float duration;

        public TransitionDesc Publish() {
            return new TransitionDesc() {
                sourceState = sourceState,
                targetState = targetState,
                duration = duration,
            };
        }
    }

    internal class AGAFieldModel_SMTransition : AGAFieldModelBase {
        public enum CompareParamSource {
            Const,
            Blackboard,
        }

        public class TransitionCondition {
            public ConditionType conditionType;
            public float exitTime;
            public AUID paramKey;
            public AUID compareParamKey;
            public int compareValueInt;
            public float compareValueFloat;
            public CompareParamSource compareParamSource;
            public ConditionParameterType paramType;
            public CompareOperator compareOperator;
            public TransitionCondition() {
                conditionType = ConditionType.ExitTime;
            }
        }

        public AUID uuid; // 在编辑处理列表时，用于查询
        public AUID sourceState; // portUuid，导出时要查询出port在列表中的序号。 -1代表任意状态
        public AUID targetState;
        public float duration;
        public List<TransitionCondition> conditions = new();

        public AGAFieldModel_SMTransition() {
            uuid = AUIDGenerator.Gen();
            conditions.Add(new TransitionCondition());
        }
        public TransitionDesc Publish(AGAPublisher.PublishContext context, AGANode_StateMachine agaNode) {

            int sourceIndex = agaNode.inputChildren.FindIndex(p => p == sourceState);
            int targetIndexIndex = agaNode.inputChildren.FindIndex(p => p == targetState);
            if (targetIndexIndex < 0) {
                throw new Exception($"目标状态有误 targetState = {targetState}");
            }
            var con = conditions.Select(c => {
                AUID paramKey = default;
                if (context.blackboard.GetEntry(c.paramKey, out var entry1)) {
                    paramKey = entry1.name;
                }
                AUID compareParamKey = default;
                if (context.blackboard.GetEntry(c.compareParamKey, out var entry2)) {
                    compareParamKey = entry2.name;
                }

                Number number = default;
                if (c.paramType == ConditionParameterType.Int) {
                    number = c.compareValueInt;
                } else {
                    number = c.compareValueFloat;
                }

                var r = new TransitionConditionDesc() {
                    conditionType = c.conditionType,
                    exitTime = c.exitTime,
                    compare = new ConditionCompareDesc() {
                        paramKey = paramKey,
                        compareParamKey = c.compareParamSource == CompareParamSource.Const ? 0 : compareParamKey,
                        compareValue = number,
                        paramType = c.paramType,
                        compareOperator = c.compareOperator,
                    },
                };
                return r;
            }).ToArray();

            return new TransitionDesc() {
                sourceState = sourceIndex,
                targetState = targetIndexIndex,
                duration = duration,
                conditions = con,
            };
        }
    }

    internal class AGAFieldModel_SelectInputMapping {
        public bool useMapping;
        public List<int2> mapping = new(); // x:传入数字, y:下标

        public int2[] Publish(AGAPublisher.PublishContext context) {
            if (!useMapping || mapping == null || mapping.Count == 0) {
                return null;
            } else {
                return mapping.ToArray();
            }
        }
    }

    internal class AGAFieldModel_ClipLink : AGAFieldModelBase {
        public AUID clipKey;

        public ClipLinkDesc Publish(AGAPublisher.PublishContext context) {
            if (clipKey == default) {
                // D.Exception($"未设置动画片段 节点uuid：{context.currentNodeUuid}"); // 允许不填动画片段
            } else {
                context.resourcesCollector.Add(clipKey);
            }
            return new ClipLinkDesc() {
                uuid = clipKey,
            };
        }
    }

    internal class AGAFieldModel_MaskLink : AGAFieldModelBase {
        public AUID maskKey;

        public MaskLinkDesc Publish(AGAPublisher.PublishContext context) {
            if (maskKey != default) {
                context.resourcesCollector.Add(maskKey);
            }
            return new MaskLinkDesc() {
                uuid = maskKey,
            };
        }
    }


    internal class AGAFieldModel_InputPort : AGAFieldModelBase {
        public string name;
        public AUID portUuid;

        public AGAFieldModel_InputPort(string name, AUID portUuid) {
            this.name = name;
            this.portUuid = portUuid;
        }

        public AGAFieldModel_InputPort(string name) {
            this.name = name;
            portUuid = AUIDGenerator.Gen();
        }
    }

    internal class AGAFieldModel_Layer : AGAFieldModelBase {
        public bool isAdditive;
        public AGAFieldModel_FloatLink weight = new();
        public AGAFieldModel_MaskLink mask = new();

        public LayerBlendNode.LayerDesc Publish(AGAPublisher.PublishContext context) {
            return new LayerBlendNode.LayerDesc() {
                isAdditive = isAdditive,
                weightDesc = weight.Publish(context),
                maskDesc = mask.Publish(context),
            };
        }
    }

    internal class AGAFieldModel_BlendSpace2DVertex : AGAFieldModelBase {
        public AGAFieldModel_ClipLink clip = new();
        public float2 position;
    }


    internal class AGAFieldModel_SequenceClipSlice : AGAFieldModelBase {
        public AGAFieldModel_ClipLink clip = new();
        public float offset;
        public float start;
        public float length;

        public static void Sort(List<AGAFieldModel_SequenceClipSlice> clipSlices) {
            // 按开始时间排序（理想情况是想要先开始的先结束）
            clipSlices.Sort((x, y) => {
                return (x.start).CompareTo(y.start);
            });
        }
    }

    internal class AGAFieldModel_BlendSpace1DClip : AGAFieldModelBase {
        public AGAFieldModel_ClipLink clip = new();
        public float position;
    }

    internal class AGAFieldModel_AxisBlend1DPort : AGAFieldModelBase {
        public AUID portUuid;
        public List<float> position = new();

        public AGAFieldModel_AxisBlend1DPort(AUID portUuid) {
            this.portUuid = portUuid;
        }
    }
}
